#ifndef TCPMGR_H
#define TCPMGR_H
#include <QTcpSocket>
#include "../_singleton.h"
#include "../Def.h"
#include <functional>
#include <QObject>
#include <QJsonArray>
#include <qcryptographichash.h>
#include <qfileinfo.h>
#include <qthread.h>
#include <memory>
#include <queue>
#include "../sql/sqlite/historydao.h"
#include "file_download.pb.h"

class TcpThread:public std::enable_shared_from_this<TcpThread> {
public:
    TcpThread();
    ~TcpThread();
    QThread* thread() {return _tcp_thread;}
private:
    QThread* _tcp_thread;
};

class TcpMgr:public QObject, public _Singleton<TcpMgr>,
               public std::enable_shared_from_this<TcpMgr>
{
    Q_OBJECT
public:
    ~TcpMgr();
private:
    friend class _Singleton<TcpMgr>;
    TcpMgr();
    void initHandlers();
    void handleMsg(ReqId id, int len, QByteArray data);
    void registerMetaType();
    QTcpSocket* _socket; // 改为指针
    QString _host;
    uint16_t _port;
    QByteArray _buffer;
    bool _b_recv_pending;
    quint16 _message_id;
    quint32 _message_len;
    std::unordered_map<ReqId, std::function<void(ReqId id, int len, QByteArray data)>> _handlers;

    //发送队列
    std::queue<QByteArray> _send_queue;
    //正在发送的包
    QByteArray _current_block;
    //当前已发送的字节数
    qint64 _bytes_sent;
    //是否正在发送
    bool _pending = false;

    // 上传上下文（记录切片发送状态）
    struct UploadContext {
        FileInfo fileInfo; // 文件基本信息
        int totalSeq; // 总切片数
        int completedSeq; // 已完成的切片序号
        bool isCompleted; // 是否所有切片发送完成
    };
    std::unordered_map<QString, UploadContext> _uploadContext; // key: file_hash

    // 下载上下文
    struct DownloadContext {
        FileInfo fileInfo;
        std::unique_ptr<QFile> outputFile; // 改为 unique_ptr
        QString savePath;
        int64_t receivedBytes = 0;
        int64_t totalSize = 0;
        QString expectedSha256;
        QByteArray receivedSha256;
        bool isFirstChunk = true;

        // 声明移动操作
        DownloadContext() = default;
        DownloadContext(DownloadContext&&) = default;
        DownloadContext& operator=(DownloadContext&&) = default;

        // 禁用拷贝操作
        DownloadContext(const DownloadContext&) = delete;
        DownloadContext& operator=(const DownloadContext&) = delete;

        // 添加便捷方法创建文件
        bool createOutputFile(const QString& path) {
            outputFile = std::make_unique<QFile>(path);
            return outputFile->open(QIODevice::WriteOnly);
        }
    };
    std::unordered_map<int64_t, DownloadContext> _downloadContext; // key: file_id

    // 用于保护上传上下文的互斥锁
    std::mutex _uploadMutex;
    // 用于保护下载上下文的互斥锁
    std::mutex _downloadMutex;

    // 初始化下载上下文
    void initializeDownloadContext(const file_download::FileDownloadRsp& rsp);
    // 处理数据块写入
    void processChunkData(DownloadContext& ctx, const file_download::FileDownloadRsp& rsp);
    //sha256计算
    QString calculateFileSha256(const QString& filePath);
    // 最终校验和清理
    void finalizeDownload(DownloadContext& ctx, const file_download::FileDownloadRsp& rsp);

public slots:
    void initSocket(); // 初始化QTcpSocket，暴露给tcpthread使用
    void slot_tcp_connect(ServerInfo);
private slots:
    void slot_send_data(ReqId reqId, QByteArray data);//保留直接发送裸请求的接口
    void slot_loginRequest(const QByteArray& data);
    void slot_sendUploadRequest(const QByteArray& data, const FileInfo& info);
    void slot_sendDownloadRequest(const QByteArray& data, const FileInfo& info);
    void slot_sendGetBackupInfoRequest(const QByteArray& data);
signals:
    void sig_con_success(bool bsuccess);
    void sig_send_data(ReqId reqId, QByteArray data);//保留直接发送裸请求的接口

    void sig_loginRequest(const QByteArray& data);
    void sig_swich_mainwindow();
    void sig_login_failed(int);

    void sig_uploadFinished(HistoryItemInfo);
    void sig_addBackupRecord(FileInfo);

    void sig_sendUploadRequest(const QByteArray& data, const FileInfo& info);
    void sig_sendDownloadRequest(const QByteArray& data, const FileInfo& info);
    void sig_downloadProgress(int fileId, qint64 bytesReceived, qint64 totalBytes);
    void sig_downloadFinished(int fileId, bool success);

    void sig_sendGetBackupInfoRequest(const QByteArray& data);
    void sig_getBackupInfoResponse(const QByteArray& response);
};

#endif // TCPMGR_H
